Fix reporting of imaginary key prefixes on toolkit tool and menu bars
authorPo Lu <luangruo@yahoo.com>
Wed, 2 Mar 2022 11:00:21 +0000 (19:00 +0800)
committerPo Lu <luangruo@yahoo.com>
Wed, 2 Mar 2022 11:02:14 +0000 (19:02 +0800)
* src/keyboard.c (make_lispy_position): Set imaginary prefix if
the terminal says what widget the position is on top of.
* src/termhooks.h (struct terminal): New field
`toolkit_position_hook'.
* src/xterm.c (x_toolkit_position): New function.
(x_create_terminal): Register hook.

src/keyboard.c
src/termhooks.h
src/xterm.c

index da8c6c54d859cd7f331b5fa7bc4fba88a536e6c5..218f9a86c86f6e865bf8d79fe605a814366de9a8 100644 (file)
@@ -5247,6 +5247,8 @@ make_lispy_position (struct frame *f, Lisp_Object x, Lisp_Object y,
   Lisp_Object window_or_frame = f
     ? window_from_coordinates (f, mx, my, &part, true, true)
     : Qnil;
+  bool tool_bar_p = false;
+  bool menu_bar_p = false;
 
   /* Report mouse events on the tab bar and (on GUI frames) on the
      tool bar.  */
@@ -5280,6 +5282,20 @@ make_lispy_position (struct frame *f, Lisp_Object x, Lisp_Object y,
         coordinates.  FIXME!  */
       window_or_frame = Qnil;
     }
+
+  if (FRAME_TERMINAL (f)->toolkit_position_hook)
+    {
+      FRAME_TERMINAL (f)->toolkit_position_hook (f, mx, my, &menu_bar_p,
+                                                &tool_bar_p);
+
+      if (NILP (track_mouse) || EQ (track_mouse, Qt))
+       {
+         if (menu_bar_p)
+           posn = Qmenu_bar;
+         else if (tool_bar_p)
+           posn = Qtool_bar;
+       }
+    }
 #endif
   if (f
       && !FRAME_WINDOW_P (f)
index b7696fed4f8eba9c5aeb930a7e310e61c655db14..8fb4837ee57ec3c54a2480421f86b03394cb3c17 100644 (file)
@@ -831,6 +831,13 @@ struct terminal
      frames on the terminal when it calls this hook, so infinite
      recursion is prevented.  */
   void (*delete_terminal_hook) (struct terminal *);
+
+  /* Called to determine whether a position is on the toolkit tool bar
+     or menu bar.  May be NULL.  It should accept five arguments
+     FRAME, X, Y, MENU_BAR_P, TOOL_BAR_P, and store true into
+     `menu_bar_p' if X and Y are in FRAME's toolkit menu bar, and true
+     into `tool_bar_p` if X and Y are in FRAME's toolkit tool bar.  */
+  void (*toolkit_position_hook) (struct frame *, int, int, bool *, bool *);
 } GCALIGNED_STRUCT;
 
 INLINE bool
index 3f6930041723d2bc89ca74e7e1376dc2d7dcd42f..9960f4930d2cc52e6003e7d518983698aff4f6c5 100644 (file)
@@ -854,6 +854,41 @@ record_event (char *locus, int type)
 
 #endif
 
+#if defined USE_X_TOOLKIT || USE_GTK
+static void
+x_toolkit_position (struct frame *f, int x, int y,
+                   bool *menu_bar_p, bool *tool_bar_p)
+{
+#ifdef USE_GTK
+  GdkRectangle test_rect;
+  int scale;
+
+  y += (FRAME_MENUBAR_HEIGHT (f)
+       + FRAME_TOOLBAR_TOP_HEIGHT (f));
+  x += FRAME_TOOLBAR_LEFT_WIDTH (f);
+
+  if (FRAME_EXTERNAL_MENU_BAR (f))
+    *menu_bar_p = (x >= 0 && x < FRAME_PIXEL_WIDTH (f)
+                  && y >= 0 && y < FRAME_MENUBAR_HEIGHT (f));
+
+  if (FRAME_X_OUTPUT (f)->toolbar_widget)
+    {
+      scale = xg_get_scale (f);
+      test_rect.x = x / scale;
+      test_rect.y = y / scale;
+      test_rect.width = 1;
+      test_rect.height = 1;
+
+      *tool_bar_p = gtk_widget_intersect (FRAME_X_OUTPUT (f)->toolbar_widget,
+                                         &test_rect, NULL);
+    }
+#else
+  *menu_bar_p = (x > 0 && x < FRAME_PIXEL_WIDTH (f)
+                && (y < 0 && y >= -FRAME_MENUBAR_HEIGHT (f)));
+#endif
+}
+#endif
+
 static void
 x_update_opaque_region (struct frame *f, XEvent *configure)
 {
@@ -17820,6 +17855,9 @@ x_create_terminal (struct x_display_info *dpyinfo)
   terminal->free_pixmap = x_free_pixmap;
   terminal->delete_frame_hook = x_destroy_window;
   terminal->delete_terminal_hook = x_delete_terminal;
+#if defined USE_X_TOOLKIT || defined USE_GTK
+  terminal->toolkit_position_hook = x_toolkit_position;
+#endif
   /* Other hooks are NULL by default.  */
 
   return terminal;